﻿using Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace NewDevice.RS232
{
    /// <summary>
    /// 万用表DM3058E控制类
    /// 提供对DM3058E数字万用表的串口控制功能
    /// </summary>
    public class DM3058E : SerialBase
    {
        // 静态构造函数，初始化量程参数
        static DM3058E()
        {
            // 直流电压量程参数 单位：V
            SetRangeParam.Add(Function.DCV, new Dictionary<string, double>
            {
                {"0",0.2 }, {"1",2}, {"2",20}, {"3",200}, {"4",1000},
            });

            // 交流电压量程参数 单位：V
            SetRangeParam.Add(Function.ACV, new Dictionary<string, double>
            {
                {"0",0.2 }, {"1",2}, {"2",20}, {"3",200}, {"4",750},
            });

            // 直流电流量程参数 单位：A
            SetRangeParam.Add(Function.DCI, new Dictionary<string, double>
            {
                {"0",0.0002 }, {"1",0.002}, {"2",0.02}, {"3",0.2}, {"4",2},{"5",10}
            });

            // 交流电流量程参数 单位：A
            SetRangeParam.Add(Function.ACI, new Dictionary<string, double>
            {
                {"0",0.02 }, {"1",0.2}, {"2",2}, {"3",10}
            });

            // 二线电阻测量量程 单位：Ω
            SetRangeParam.Add(Function.WR2, new Dictionary<string, double>
            {
                {"0",200 }, {"1",2000}, {"2",20000}, {"3",200000}, {"4",2000000},{"5",10000000},{"6",100000000}
            });

            // 四线电阻测量量程 单位：Ω
            SetRangeParam.Add(Function.WR4, new Dictionary<string, double>
            {
                {"0",200 }, {"1",2000}, {"2",20000}, {"3",200000}, {"4",1000000},{"5",10000000},{"6",100000000}
            });

            // 频率测量时输入信号的电压量程 单位：V
            SetRangeParam.Add(Function.FREQ, new Dictionary<string, double>
            {
                {"0",0.2 }, {"1",2}, {"2",20}, {"3",200}, {"4",750},
            });

            // 周期测量时输入电压的量程 单位：V
            SetRangeParam.Add(Function.PERI, new Dictionary<string, double>
            {
                {"0",0.2 }, {"1",2}, {"2",20}, {"3",200}, {"4",750},
            });

            // 短路测量时的极限电阻值 单位：Ω
            SetRangeParam.Add(Function.CONT, new Dictionary<string, double>
            {
                {"MIN",1 }, {"MAX",2000}
            });

            // 电容测量量程 单位：微法，最大量程位10毫法
            SetRangeParam.Add(Function.CAP, new Dictionary<string, double>
            {
                {"0",0.002 }, {"1",0.02}, {"2",0.2}, {"3",2}, {"4",200},{"5",10000}
            });
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="deviceName">设备名称，默认为"万用表DM3058E"</param>
        public DM3058E(string deviceName = "万用表DM3058E") : base(deviceName)
        {
        }

        /// <summary>
        /// 设置测试精度指令映射
        /// 存储各功能对应的量程参数
        /// </summary>
        private static Dictionary<Function, Dictionary<string, double>> SetRangeParam = new Dictionary<Function, Dictionary<string, double>>();

        /// <summary>
        /// 获取量程命令映射
        /// 存储各功能对应的获取量程命令
        /// </summary>
        private static Dictionary<Function, string> GetRangeCmd = new Dictionary<Function, string>
            {
                {Function.DCV,":MEASure:VOLTage:DC" },
                {Function.ACV,":MEASure:VOLTage:AC" },
                {Function.DCI,":MEASure:CURRent:DC" },
                {Function.ACI,":MEASure:CURRent:AC" },
                {Function.WR2,":MEASure:RESistance" },
                {Function.WR4,":MEASure:FRESistance" },
                {Function.FREQ,":MEASure:FREQuency" },
                {Function.PERI,":MEASure:PERiod" },
                {Function.CONT,":MEASure:CONTinuity" },
                {Function.CAP,":MEASure:CAPacitance" }
            };

        /// <summary>
        /// 设置功能命令映射
        /// 存储各功能对应的设置命令
        /// </summary>
        private static Dictionary<Function, string> SetFunctionCmd = new Dictionary<Function, string>
            {
                { Function.DCV,":FUNCtion:VOLTage:DC"},
                { Function.ACV,":FUNCtion:VOLTage:AC"},
                { Function.DCI,":FUNCtion:CURRent:DC"},
                { Function.ACI,":FUNCtion:CURRent:AC"},
                { Function.WR2,":FUNCtion:RESistance"},
                { Function.WR4,":FUNCtion:FRESistance"},
                { Function.FREQ,":FUNCtion:FREQuency"},
                { Function.PERI,":FUNCtion:PERiod"},
                { Function.CONT,":FUNCtion:CONTinuity"},
                { Function.DIODE,":FUNCtion:DIODe"},
                { Function.CAP,":FUNCtion:CAPacitance"}
            };

        /// <summary>
        /// 命令结束符
        /// </summary>
        private const string StopCode = "\r\n";

        /// <summary>
        /// 读取当前设备状态
        /// </summary>
        /// <returns>当前功能枚举值</returns>
        public Function GetFunction()
        {
            string result = SendAsciiStringAndWaitResponse(":FUNCtion?" + StopCode);
            // 处理特殊返回值
            if (result == "2WR")
            {
                result = "WR2";
            }
            else if (result == "4WR")
            {
                result = "WR4";
            }

            // 匹配枚举值
            if (result != null)
            {
                foreach (Function item in Enum.GetValues(typeof(Function)))
                {
                    if (result == item.ToString())
                    {
                        Function = item;
                        return item;
                    }
                }
            }
            return 0;
        }

        /// <summary>
        /// 设置量程
        /// </summary>
        /// <param name="value">要设置的量程值</param>
        /// <exception cref="Exception">当量程值超出范围时抛出异常</exception>
        public void SetRange(double value)
        {
            // 二极管测试不需要设置量程
            if (Function == Function.DIODE)
            {
                return;
            }

            string cmd = "";
            string cmdHead = GetRangeCmd[Function];

            // 短路测试特殊处理
            if (Function == Function.CONT)
            {
                double max = SetRangeParam[Function]["MAX"];
                double min = SetRangeParam[Function]["MIN"];
                if (value > max | value < min)
                {
                    throw new Exception($"{Function.ToString()}参数错误{value}");
                }
                cmd = cmdHead + " " + (int)value;
            }
            else
            {
                bool update = false;
                var param = SetRangeParam[Function];

                // 查找合适的量程
                foreach (var item in param)
                {
                    if (item.Value >= value)
                    {
                        cmd = cmdHead + " " + item.Key;
                        update = true;
                        break;
                    }
                }

                if (!update)
                {
                    throw new Exception($"{Function.ToString()}错误的量程{value}");
                }
            }

            // 发送设置命令
            SendAsciiString(cmd + StopCode);
        }

        /// <summary>
        /// 获取当前量程
        /// </summary>
        /// <returns>当前量程字符串</returns>
        public string GetRange()
        {
            string cmd = GetRangeCmd[Function] + ":RANGe?";
            string result = SendAsciiStringAndWaitResponse(cmd + StopCode);
            return result;
        }

        /// <summary>
        /// 设置当前万用表功能
        /// </summary>
        /// <param name="func">要设置的功能枚举</param>
        /// <exception cref="Exception">当设置失败时抛出异常</exception>
        public void SetFunction(Function func)
        {
            string cmd = SetFunctionCmd[func];
            SendAsciiString(cmd + StopCode);
            Thread.Sleep(500);  // 等待设备响应

            // 验证设置是否成功
            if (func != GetFunction())
            {
                throw new Exception($"{deviceName} 设置{func}功能异常");
            }
        }

        /// <summary>
        /// 当前功能属性
        /// </summary>
        public Function Function { get; set; }

        /// <summary>
        /// 获取当前功能状态的值
        /// </summary>
        /// <returns>测量值</returns>
        public double GetValue()
        {
            string cmd = GetRangeCmd[Function] + "?";
            double result = double.Parse(SendAsciiStringAndWaitResponse(cmd + StopCode));
            Mylog.Info(deviceName: deviceName, message: $"FUNC={Function.ToString()},Value=[{result}]");
            return result;
        }
    }

    /// <summary>
    /// 万用表功能枚举
    /// </summary>
    public enum Function
    {
        /// <summary>
        /// 直流电压测量功能
        /// </summary>
        DCV,

        /// <summary>
        /// 交流电压测量功能
        /// </summary>
        ACV,

        /// <summary>
        /// 直流电流测量功能
        /// </summary>
        DCI,

        /// <summary>
        /// 交流电流测量功能
        /// </summary>
        ACI,

        /// <summary>
        /// 二线电阻测量功能
        /// </summary>
        WR2,

        /// <summary>
        /// 四线电阻测量功能
        /// </summary>
        WR4,

        /// <summary>
        /// 频率测量功能
        /// </summary>
        FREQ,

        /// <summary>
        /// 周期测量功能
        /// </summary>
        PERI,

        /// <summary>
        /// 短路测量功能
        /// </summary>
        CONT,

        /// <summary>
        /// 二极管测量功能
        /// </summary>
        DIODE,

        /// <summary>
        /// 电容测量功能
        /// </summary>
        CAP
    }
}